using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Reflection;

using ImageRecognition2.Forms;

using LowLevelGraphics.Filter;
using LowLevelGraphics;

using AVICapWrapper;

namespace LowLevelGraphics.Forms
{
    /// <summary>
    /// 
    /// </summary>
    public partial class FormCapture : Form
    {
        protected IFilter m_Filter = null;
        protected Bitmap m_OriginalImage = null;
        protected Bitmap m_FilteredImage = null;
        protected Bitmap m_Image = null;
        protected Form formFullScreen = new Form();

        /// <summary>
        /// 
        /// </summary>
        public FormCapture()
        {
            InitializeComponent();

            GC.KeepAlive(aviCapture1);
            GC.SuppressFinalize(aviCapture1);
            videoFormatBox.Items.Add(new Size(160, 120));
            videoFormatBox.Items.Add( new Size( 320, 240 ));
            videoFormatBox.Items.Add( new Size( 640, 480 ));
            videoFormatBox.SelectedIndexChanged += new EventHandler(videoFormatBox_SelectedIndexChanged);
            videoFormatBox.SelectedIndex = 1;

            frameRateBar.Value = 10;
            frameRateBar_Scroll( this, new EventArgs() );
            
            aviCapture1.SetVideoFormat(( Size ) videoFormatBox.Items[videoFormatBox.SelectedIndex] );
            aviCapture1.OnFrameReceived += new AVICapture.FrameCallbackEvent(this.FrameCallbackHandler);
            aviCapture1.StartStreaming();
            aviCapture1.BackgroundImageLayout = ImageLayout.Zoom;

            pictureBox1.BackgroundImageLayout = ImageLayout.Zoom;

            frameRateBar.Value = 10;

            foreach(Type type in Definitions.FilterList())
            {
                this.comboBox1.Items.Add(new FilterItem(type));
            }

            this.comboBox1.SelectedIndex = 0;
            this.comboBox1.Sorted = true;
            this.comboBox1.SelectedIndexChanged += new EventHandler(comboBox1_SelectedIndexChanged);

            InitializeAutoComplete();

            this.pictureBox1.DoubleClick += delegate(object sender, EventArgs e)
            {
                ApplyFiltered();
            };

            this.aviCapture1.DoubleClick += delegate(object sender, EventArgs e)
            {
                ApplyOriginal();
            };
        }

        /// <summary>
        /// Initialize Auto Complete 
        /// </summary>
        private void InitializeAutoComplete()
        {
            this.comboBox1.DropDownStyle = ComboBoxStyle.DropDown;
            AutoCompleteStringCollection aAutoCompleteFilterList = Definitions.GetAutoCompleteFromFilterList();
            comboBox1.AutoCompleteCustomSource = aAutoCompleteFilterList;
            comboBox1.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
            comboBox1.AutoCompleteSource = AutoCompleteSource.CustomSource;
        }

        /// <summary>
        /// return the clicked image
        /// </summary>
        /// <value>The image.</value>
        public Image Image
        {
            get { return m_Image; }
        }

        /// <summary>
        /// Handles the SelectedIndexChanged event of the comboBox1 control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            FilterItem filterItem = (FilterItem)comboBox1.SelectedItem;
            m_Filter = (IFilter)Activator.CreateInstance(filterItem.Type);
        }

        /// <summary>
        /// Handles the SelectedIndexChanged event of the videoFormatBox control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected void videoFormatBox_SelectedIndexChanged( object sender, EventArgs e )
        {
            Size newSize = ( Size ) videoFormatBox.Items[videoFormatBox.SelectedIndex];

            aviCapture1.StopStreaming();
            aviCapture1.SetVideoFormat( newSize );
            
            // Setting surrounding Group Box Size
            cameraGroupBox.Size = new Size( newSize.Width + 15, newSize.Height + 30 );

            // Setting group Box size for Buffer Image
            bufferGroupBox.Size = new Size( newSize.Width + 15, newSize.Height + 30 );
            bufferGroupBox.Location = new Point( cameraGroupBox.Location.X + cameraGroupBox.Size.Width + 11, bufferGroupBox.Location.Y );

            // Setting new Size for Buffer Image
            pictureBox1.Size = newSize;

            aviCapture1.StartStreaming();

        }

        /// <summary>
        /// Frames the callback handler.
        /// </summary>
        /// <param name="handleCapture">The handle capture.</param>
        /// <param name="videoHeader">The video header.</param>
        private void FrameCallbackHandler( IntPtr handleCapture, IntPtr videoHeader )
        {
            Bitmap bmp = aviCapture1.GetBitmapFromUnmanagedPtr( videoHeader );
            m_OriginalImage = bmp;
            if (m_Filter != null) m_Filter.Execute(bmp).Dispose();
            pictureBox1.Image = bmp;
            m_FilteredImage = bmp;
        }

        /// <summary>
        /// Handles the Scroll event of the frameRateBar control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void frameRateBar_Scroll( object sender, EventArgs e )
        {
            textBox1.Text = frameRateBar.Value.ToString();
            aviCapture1.SetFrameRate( frameRateBar.Value );
        }

        /// <summary>
        /// Handles the Click event of the cbPropertyGrid control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void cbPropertyGrid_Click(object sender, EventArgs e)
        {
            if (m_Filter != null)
            {
                Form form = new Form();
                PropertyGrid propertyGrid = new PropertyGrid();
                propertyGrid.Parent = form;
                propertyGrid.Dock = DockStyle.Fill;
                propertyGrid.SelectedObject = m_Filter;
                propertyGrid.PropertyValueChanged += new PropertyValueChangedEventHandler(propertyGrid_PropertyValueChanged);
                form.Show();
            }
        }

        void propertyGrid_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Handles the Click event of the cbApplyOriginal control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void cbApplyOriginal_Click(object sender, EventArgs e)
        {
            ApplyOriginal();
        }

        /// <summary>
        /// Applies the original.
        /// </summary>
        private void ApplyOriginal()
        {
            m_Image = m_OriginalImage;
            this.DialogResult = DialogResult.OK;
            this.Close();
        }

        /// <summary>
        /// Handles the Click event of the cbApplyFiltered control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void cbApplyFiltered_Click(object sender, EventArgs e)
        {
            ApplyFiltered();
        }

        /// <summary>
        /// Applies the filtered.
        /// </summary>
        private void ApplyFiltered()
        {
            m_Image = m_FilteredImage;
            this.DialogResult = DialogResult.OK;
            this.Close();
        }

        /// <summary>
        /// Handles the Click event of the cbMacro control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void cbMacro_Click(object sender, EventArgs e)
        {
            FormMacro formMacro = new FormMacro();
            formMacro.Show();
        }

        /// <summary>
        /// Handles the Click event of the cbFullScreenCapture control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void cbFullScreenCapture_Click(object sender, EventArgs e)
        {
            aviCapture1.Size = this.Size;
            aviCapture1.Dock = DockStyle.Fill;
        }

        private void cbFullScreenProcessed_Click(object sender, EventArgs e)
        {
            pictureBox1.Size = this.Size;
            pictureBox1.Dock = DockStyle.Fill;
        }

        private void videoFormatBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Return || e.KeyCode == Keys.Enter)
            {

            }
        }
    }

    /// <summary>
    /// Just used for displaying filters in here
    /// </summary>
    public class FilterItem
    {
        /// <summary>
        /// 
        /// </summary>
        protected Type m_Type = typeof(void);


        /// <summary>
        /// Initializes a new instance of the <see cref="FilterItem"/> class.
        /// </summary>
        /// <param name="_type">The _type.</param>
        public FilterItem(Type _type)
        {
            m_Type = _type;
        }

        /// <summary>
        /// Gets or sets the type.
        /// </summary>
        /// <value>The type.</value>
        public Type Type
        {
            get { return m_Type; }
            set { m_Type = value; }
        }

        /// <summary>
        /// Returns a <see cref="System.String"/> that represents this instance.
        /// </summary>
        /// <returns>
        /// A <see cref="System.String"/> that represents this instance.
        /// </returns>
        public override string ToString()
        {
            return m_Type.Name;
        }
    }

}